package cn.innosmart.aq.manager;

import com.tutk.p2p.ConnectionEntity;
import com.tutk.p2p.ResponseHandler;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;

import cn.innosmart.aq.bean.DeviceBean;
import cn.innosmart.aq.util.SystemConstant;

/**
 * Created by David on 2015/6/30.
 */
public class DeviceManager extends BaseManager {
    private static IncludeCallBack includeCallBackCallBack;
    private static ControlCallBack controlCallBack;
    private static UpdateCallBack updateCallBack;
    private String Tag = "DeviceManager";
    //添加设备回调
    private ResponseHandler.ResponseCallback mDeviceStartIncludeCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            connectionEntity.flags.remove(connectionEntity.DEVICEINCLUDE);
            JSONObject jRoot = null;
            int ret = -1;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (includeCallBackCallBack != null) {
                        includeCallBackCallBack.onIncludeResponseCallBack(0);
                    }
                    ret = 0;
                } else {
                    log(Tag, "DeviceManager.Include fail: " + rspMsg);
                }
            } catch (Exception e) {

            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(ret, connectionEntity.DEVICEINCLUDE, null);
            }

        }
    };
    //删除设备回调
    private ResponseHandler.ResponseCallback mDeviceStartExcludeCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.StartExclude get response=" + message);
            connectionEntity.flags.remove(connectionEntity.DEVICEEXCLUDE);
            JSONObject jRoot = null;
            int ret = -1;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (includeCallBackCallBack != null) {
                        includeCallBackCallBack.onIncludeResponseCallBack(0);
                    }
                    ret = 0;
                }
            } catch (Exception e) {

            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(ret, connectionEntity.DEVICEEXCLUDE, null);
            }
        }
    };
    //撤销模式回调
    private ResponseHandler.ResponseCallback mDeviceAbortInclusionExclusionCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.AbortInclusionExclusion get response=" + message);
            connectionEntity.flags.remove(connectionEntity.ABORTMODE);
        }
    };
    /**
     * {"address":"zwave://e5ad378b/21/49/1/2","name":"Water Level Sensor","devicetype":"Water Level Sensor","functype":101,"label":"Water Level Sensor"}
     * {"code":0,"message":"Success",
     * "result":{"channels":[{"address":"zwave://da887909/17/49/1/2","devicetype":"PH Temperature Sensor","functype":100,"name":"PH","place":"SN0121_fyHw43GNPCsXEiYVUNw9","basicvalue":8.210000,"sensorvalue":8.210000,"sensorunit":-1},
     * {"address":"zwave://da887909/17/49/1/23","devicetype":"PH Temperature Sensor","functype":11,"name":"Water Temperature","place":"SN0121_fyHw43GNPCsXEiYVUNw9","basicvalue":283.100000,"sensorvalue":283.100000,"sensorunit":1},
     * {"address":"zwave://da887909/17/112/1/1","devicetype":"PH Temperature Sensor","functype":32,"name":"1. Report Time Factor","basicvalue":null,"sensorvalue":null,"sensorunit":null},
     * {"address":"zwave://da887909/23/49/1/2","devicetype":"Water Level Sensor","functype":101,"name":"Water Level Sensor","place":"SN0121_fyHw43GNPCsXEiYVUNw9","basicvalue":1,"sensorvalue":1,"sensorunit":-1},
     * {"address":"zwave://da887909/23/113/1/1","devicetype":"Water Level Sensor","functype":31,"name":"Tamper Sensor","basicvalue":null,"sensorvalue":null,"sensorunit":null}]}
     * ,"type":"resp","callid":1438219862,"method":"DeviceManager.List"}
     */
    /**
     * ListDevice列表回调
     */
    private ResponseHandler.ResponseCallback mDeviceListCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.List get response=" + message);
            connectionEntity.flags.remove(connectionEntity.DEVICELIST);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    JSONArray jsonArray = jRoot.getJSONObject("result").getJSONArray("channels");
                    DeviceBean deviceBean;
                    if (SystemConstant.deviceBeanHashMap == null) {
                        SystemConstant.deviceBeanHashMap = new HashMap<String, DeviceBean>();
                    } else {
                        SystemConstant.deviceBeanHashMap.clear();
                    }
                    System.out.println("jsonArray=" + jsonArray.length());
                    //将String初始化成内存设备数据
                    for (int i = 0; i < jsonArray.length(); i++) {
                        System.out.println("ADD");
                        deviceBean = new DeviceBean(jsonArray.getJSONObject(i));
                        System.out.println(deviceBean.toString());
                        SystemConstant.deviceBeanHashMap.put(deviceBean.getAddress(), deviceBean);
                    }

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(0, connectionEntity.DEVICELIST, null);
            }
        }
    };
    /**
     * 设备控制回调函数
     */
    private ResponseHandler.ResponseCallback mDeviceControlCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.Control get response=" + message);
            connectionEntity.flags.remove(connectionEntity.DEVICECONTROL);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (controlCallBack != null) {
                        controlCallBack.onControlResponseCallBack(0);
                    }
                } else {
                    if (controlCallBack != null) {
                        controlCallBack.onControlResponseCallBack(-1);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(0, connectionEntity.DEVICECONTROL, null);
            }
        }
    };
    /**
     * 更新设备数据回调函数
     */
    private ResponseHandler.ResponseCallback mDeviceUpdateCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.Update get response=" + message);
            connectionEntity.flags.remove(connectionEntity.DEVICEUPDATE);
            JSONObject jRoot = null;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    //成功
                    if (updateCallBack != null) {
                        updateCallBack.onUpdateResponseCallBack(0);
                    }
                } else {
                    //失败
                    if (updateCallBack != null) {
                        updateCallBack.onUpdateResponseCallBack(-1);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                //失败
                if (updateCallBack != null) {
                    updateCallBack.onUpdateResponseCallBack(-2);
                }
            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(0, connectionEntity.DEVICEUPDATE, null);
            }
        }
    };
    /**
     * 删除失败节点回调函数
     */
    private ResponseHandler.ResponseCallback mDeviceRemoveFailedNodeCallBack = new ResponseHandler.ResponseCallback() {
        @Override
        public void onResponseCallback(ConnectionEntity connectionEntity, String message) {
            log(Tag, "DeviceManager.StartExclude get response=" + message);
            connectionEntity.flags.remove(connectionEntity.REMOVEFAILEDNODE);
            JSONObject jRoot = null;
            int ret = -1;
            try {
                jRoot = new JSONObject(message);
                int rspCode = jRoot.getInt("code");
                String rspMsg = jRoot.getString("message");
                if (0 == rspCode && "Success".equals(rspMsg)) {
                    if (includeCallBackCallBack != null) {
                        includeCallBackCallBack.onIncludeResponseCallBack(0);
                    }
                    ret = 0;
                }
            } catch (Exception e) {

            }
            if (connectionEntity.iConnectionEntity != null) {
                connectionEntity.iConnectionEntity.onBoxMessageOver(ret, connectionEntity.DEVICEEXCLUDE, null);
            }
        }
    };

    private DeviceManager() {
    }

    public static DeviceManager getInstance() {
        return DeviceManagerInstance.instance;
    }

    // DeviceManager.StartInclude
    public boolean StartInclude(ConnectionEntity connectionEntity) {
        log(Tag, "StartInclude");
        connectionEntity.flags.add(connectionEntity.DEVICELIST);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceStartIncludeCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.StartInclude", "{}", callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    public boolean StartInclude(ConnectionEntity connectionEntity, IncludeCallBack includeCallBack) {
        log(Tag, "StartInclude");
        this.includeCallBackCallBack = includeCallBack;
        connectionEntity.flags.add(connectionEntity.DEVICEINCLUDE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceStartIncludeCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.StartInclude", "{}", callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // DeviceManager.StartExclude
    public boolean StartExclude(ConnectionEntity connectionEntity) {
        log(Tag, "StartExclude");
        connectionEntity.flags.add(connectionEntity.DEVICEEXCLUDE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceStartExcludeCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.StartExclude", "{}", callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // DeviceManager.AbortInclusionExclusion
    public boolean AbortInclusionExclusion(ConnectionEntity connectionEntity) {
        log(Tag, "AbortInclusionExclusion");
        connectionEntity.flags.add(connectionEntity.ABORTMODE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceAbortInclusionExclusionCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.AbortInclusionExclusion", "{}", callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }
//{"code":0,"message":"Success","type":"resp","callid":1439531306,"method":"DeviceManager.Control"}

    // DeviceManager.List
    public boolean List(ConnectionEntity connectionEntity) {
//        log(Tag, "List. params = " + params);
        // 定义该指令的Handler, 设置回调处理函数, 添加到 HashMap 中
        connectionEntity.flags.add(connectionEntity.DEVICELIST);
        long callid = System.currentTimeMillis() / 1000;
        JSONObject jParams = new JSONObject();
        try {
            jParams.put("address", "zwave://0/27/*/*");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceListCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.List", jParams.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    public boolean List(ConnectionEntity connectionEntity, int delay) {
//        log(Tag, "List. params = " + params);
        // 定义该指令的Handler, 设置回调处理函数, 添加到 HashMap 中
        connectionEntity.flags.add(connectionEntity.DEVICELIST);
        long callid = System.currentTimeMillis() / 1000;
        if (delay != 0) {
            callid = callid + delay;
        }
        JSONObject jParams = new JSONObject();
        try {
            jParams.put("address", "zwave://0/27/*/*");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceListCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.List", jParams.toString(), callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    private static long lastControlTimestamp = 0;

    // DeviceManager.Control
    public boolean Control(ConnectionEntity connectionEntity, String params, ControlCallBack controlCallBack) {
        long now = System.currentTimeMillis();
        if (now - lastControlTimestamp > 1 * 1000) {
            lastControlTimestamp = now;
            log(Tag, "Control. params = " + params);
            this.controlCallBack = controlCallBack;
            connectionEntity.flags.add(connectionEntity.DEVICECONTROL);
            long callid = System.currentTimeMillis() / 1000;
            ResponseHandler handler = new ResponseHandler();
            handler.setCallback(mDeviceControlCallBack);
            connectionEntity.mReqRspHashMap.put(callid, handler);
            if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.Control", params, callid)) {
                connectionEntity.mReqRspHashMap.remove(callid);
                return false;
            } else {
                return true;
            }
        }

        return false;
    }

    // DeviceManager.Update
    public boolean Update(ConnectionEntity connectionEntity, String params) {
        log(Tag, "Update. params = " + params);
        connectionEntity.flags.add(connectionEntity.DEVICEUPDATE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceUpdateCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.Update", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    public boolean Update(ConnectionEntity connectionEntity, String params, UpdateCallBack updateCallBack) {
        log(Tag, "Update. params = " + params);
        this.updateCallBack = updateCallBack;
        connectionEntity.flags.add(connectionEntity.DEVICEUPDATE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceUpdateCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.Update", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    // DeviceManager.RemoveFailedNode
    public boolean RemoveFailedNode(ConnectionEntity connectionEntity, String params) {
        log(Tag, "StartExclude");
        connectionEntity.flags.add(connectionEntity.REMOVEFAILEDNODE);
        long callid = System.currentTimeMillis() / 1000;
        ResponseHandler handler = new ResponseHandler();
        handler.setCallback(mDeviceRemoveFailedNodeCallBack);
        connectionEntity.mReqRspHashMap.put(callid, handler);
        if (!SendCommand(connectionEntity, connectionEntity.getUid(), "DeviceManager.RemoveFailedNode", params, callid)) {
            connectionEntity.mReqRspHashMap.remove(callid);
            return false;
        } else {
            return true;
        }
    }

    public interface IncludeCallBack {
        void onIncludeResponseCallBack(int ret);
    }

    public interface ControlCallBack {
        void onControlResponseCallBack(int ret);
    }

    public interface UpdateCallBack {
        void onUpdateResponseCallBack(int ret);
    }

    private static class DeviceManagerInstance {
        private static final DeviceManager instance = new DeviceManager();
    }
}
